Conversation
4ef2eeb to
46478d9
Compare
| type Deposit struct { | ||
| Proof []string `json:"proof" validate:"required"` | ||
| Data DepositData `json:"data" validate:"required"` | ||
| Proof []string `json:"proof" validate:"required,dive,hexadecimal"` |
There was a problem hiding this comment.
is it worth adding this check for hexadecimal here? we have to convert it anyways
There was a problem hiding this comment.
Very good question. Actually our decoding error message is far superior than the one from the validate package. For now we can leave it, but we should reevaluate if we even want to use validate since we need to decode anyway.
|
I will squish commits and fix any rebasing needed through review |
| type Phase0ProduceBlockV3Response struct { | ||
| Version string `json:"version" validate:"required"` | ||
| ExecutionPayloadBlinded bool `json:"execution_payload_blinded"` | ||
| ExeuctionPayloadValue string `json:"exeuction_payload_value"` |
There was a problem hiding this comment.
The file name is too generic. What's the difference between structs.go and api_structs.go? I would name this one structs_block.go to let know blocks are defined here.
| errJson := &http2.DefaultErrorJson{ | ||
| Message: "slot is required", | ||
| Code: http.StatusBadRequest, | ||
| } | ||
| http2.WriteError(w, errJson) |
There was a problem hiding this comment.
you can use http2.HandleError here and everywhere else to make the code smaller
| http2.WriteError(w, errJson) | ||
| return | ||
| } | ||
| slot, err := strconv.ParseUint(rawSlot, 10, 64) |
There was a problem hiding this comment.
It's better to write this instead:
slot, valid = shared.ValidateUint(w, "Slot", rawSlot)
if !valid {
return
}
| return | ||
| } | ||
| if optimistic { | ||
| http2.HandleError(w, "The node is currently optimistic and cannot serve validators", http.StatusInternalServerError) |
There was a problem hiding this comment.
I would use 503 Status Unavailable here
| w.Header().Set(api.ExecutionPayloadBlindedHeader, fmt.Sprintf("%v", isBlinded)) | ||
| w.Header().Set(api.ExecutionPayloadValueHeader, fmt.Sprintf("%d", payloadValue)) |
There was a problem hiding this comment.
You can set these headers immediately after you receive the response from the v1alpha1 server. This will reduce duplication and you will not need to pass isBlinded anymore.
There was a problem hiding this comment.
i set it but it's still used in the response, moved it outside
| blindedBellatrixBlock, ok := v1alpha1resp.Block.(*eth.GenericBeaconBlock_BlindedBellatrix) | ||
| if ok { | ||
| handleProduceBlindedBellatrixV3(isSSZ, blindedBellatrixBlock, w, validate, v1alpha1resp.IsBlinded, v1alpha1resp.PayloadValue) | ||
| return | ||
| } | ||
| bellatrixBlock, ok := v1alpha1resp.Block.(*eth.GenericBeaconBlock_Bellatrix) | ||
| if ok { | ||
| handleProduceBellatrixV3(isSSZ, bellatrixBlock, w, validate, v1alpha1resp.IsBlinded, v1alpha1resp.PayloadValue) | ||
| return |
There was a problem hiding this comment.
this can be inside a conditional
if v1alpha1resp.IsBlinded {
// check blinded
} else {
// check unblinded
}
same for capella and deneb
There was a problem hiding this comment.
what do you mean by this shouldn't it match the type check?
There was a problem hiding this comment.
What I mean is that it doesn't make sense to type check for a blinded block when v1alpha1resp.IsBlinded == false and vice versa.
| http2.HandleError(w, err.Error(), http.StatusInternalServerError) | ||
| return | ||
| } | ||
| if err = validate.Struct(block); err == nil { |
There was a problem hiding this comment.
I would not validate the response. You normally only validate requests. Also this code is incorrect because nothing will happen and 200 will be returned when error is not nil.
| http2.WriteJson(w, &Phase0ProduceBlockV3Response{ | ||
| Version: version.String(version.Phase0), | ||
| ExecutionPayloadBlinded: false, | ||
| ExeuctionPayloadValue: fmt.Sprintf("%d", payloadValue), // mev not available at this point |
There was a problem hiding this comment.
what does this comment mean?
There was a problem hiding this comment.
I was thinking since it's local build it's not available 🤔 but maybe i'm wrong in that assumption
| package beacon | ||
|
|
||
| type Phase0ProduceBlockV3Response struct { | ||
| Version string `json:"version" validate:"required"` |
There was a problem hiding this comment.
As stated in another place, I would not add validate to responses nor would I validate them. A validation error will return 400 Bad Request, but it's not the user's request that was incorrect.
terencechain
left a comment
There was a problem hiding this comment.
My only feedback is today we can get the value from builder payload, we can't get the value from local payload. It seems the natural progression is to add value to local payload ExecutionData. Doing so, we can remove values for block
consensus-types/blocks/types.go
Outdated
| type BeaconBlockBody struct { | ||
| version int | ||
| isBlinded bool | ||
| valueInGwei uint64 |
There was a problem hiding this comment.
I think valueInGwei should either be inside the ExecutionData or BeaconBlock. ExecutionData is more appropriate but I'd hate to make you do this in this PR. Feel free to do this in another PR or open an issue for someone else to do it
There was a problem hiding this comment.
let me think about that see if it'd be better to move it or clean this one up
| } | ||
|
|
||
| message GenericBeaconBlock { | ||
|
|
| // If we can't get the builder value, just use local block. | ||
| if higherValueBuilder && withdrawalsMatched { // Builder value is higher and withdrawals match. | ||
| blk.SetBlinded(true) | ||
| blk.SetValueInGwei(builderValueGwei) |
There was a problem hiding this comment.
Better to move this before the return nil after the else
| blk.SetBlinded(false) | ||
| localPayloadValue, err := localPayload.ValueInGwei() | ||
| if err == nil { | ||
| blk.SetValueInGwei(localPayloadValue) | ||
| } | ||
| return blk.SetExecution(localPayload) |
There was a problem hiding this comment.
There's no local payload value for Bellatrix, I'd just remove these. Will love to remove any complexity
| localPayloadValue, err := localPayload.ValueInGwei() | ||
| if err == nil { | ||
| blk.SetValueInGwei(localPayloadValue) | ||
| } |
There was a problem hiding this comment.
Same here. We can remove these
| func (bs *Server) ProduceBlockV3(w http.ResponseWriter, r *http.Request) { | ||
| ctx, span := trace.StartSpan(r.Context(), "validator.ProduceBlockV3") | ||
| defer span.End() | ||
| if ok := bs.checkSync(r.Context(), w); !ok { |
There was a problem hiding this comment.
You should pass ctx inside. Also, can you add a new line after defer span.End()?
| if rawSkipRandaoVerification == "true" { | ||
| randaoReveal = primitives.PointAtInfinity | ||
| } else { | ||
| rr, err := hexutil.Decode(rawRandaoReveal) |
There was a problem hiding this comment.
Ok that's true... In that case maybe let's return bytes from shared.ValidateHex. What do you think? And inside the function use hexutil.Decode instead of bytesutil.IsHex
| } | ||
|
|
||
| func produceBlockV3(context context.Context, bs *Server, w http.ResponseWriter, r *http.Request, v1alpha1req *eth.BlockRequest) { | ||
| ctx, span := trace.StartSpan(context, "validator.ProduceBlockV3.internal") |
There was a problem hiding this comment.
Is this useful? Same comment for other spans in private functions
There was a problem hiding this comment.
hmm maybe not maybe I should just pass it down
| blindedBellatrixBlock, ok := v1alpha1resp.Block.(*eth.GenericBeaconBlock_BlindedBellatrix) | ||
| if ok { | ||
| handleProduceBlindedBellatrixV3(isSSZ, blindedBellatrixBlock, w, validate, v1alpha1resp.IsBlinded, v1alpha1resp.PayloadValue) | ||
| return | ||
| } | ||
| bellatrixBlock, ok := v1alpha1resp.Block.(*eth.GenericBeaconBlock_Bellatrix) | ||
| if ok { | ||
| handleProduceBellatrixV3(isSSZ, bellatrixBlock, w, validate, v1alpha1resp.IsBlinded, v1alpha1resp.PayloadValue) | ||
| return |
There was a problem hiding this comment.
What I mean is that it doesn't make sense to type check for a blinded block when v1alpha1resp.IsBlinded == false and vice versa.
| log.WithError(err).Error("Checking for SSZ failed, defaulting to JSON") | ||
| isSSZ = false | ||
| } | ||
| v1alpha1resp, err := bs.V1Alpha1ValidatorServer.GetBeaconBlock(r.Context(), v1alpha1req) |
db2eae1 to
7caf026
Compare
0e81971 to
2fdb790
Compare
c622bbd to
ca3766f
Compare
963fefc to
ce697f3
Compare
2926e2b to
811104d
Compare
7b5fdfa to
e166e5d
Compare
261d8ee to
65d310e
Compare
65d310e to
065368e
Compare
| } | ||
|
|
||
| // DecodeWithLength takes a string and a length and validates the hex while returning an error | ||
| func DecodeWithLength(s string, length int) ([]byte, error) { |
There was a problem hiding this comment.
I would rename it to DecodeHexWithLength. Otherwise the caller will have to go into the function to understand it.
| } | ||
|
|
||
| // DecodeWithMaxLength takes a string and a max byte length and validates the hex while returning an error | ||
| func DecodeWithMaxLength(s string, length int) ([]byte, error) { |
There was a problem hiding this comment.
Similarly, I would rename to DecodeHexWithMaxLength
| if !math.IsValidUint256(uint256) { | ||
| return nil, errors.New("is") | ||
| } |
There was a problem hiding this comment.
Error message is incomplete. But do we even have to validate this once ok passes?
There was a problem hiding this comment.
oh weird ok not sure how that cut off will fix
There was a problem hiding this comment.
A few comments on this file:
- It would be nice to use
NewDecodeErrorwhere possible. As a small nitpick, in other conversion code we do not add the name of the object to the error message. So instead of writingNewDecodeError(err, phase0SignedBeaconBlock.Signature)we writeNewDecodeError(err, Signature). This is mostly because a user does not send anything calledphase0SignedBeaconBlockin the request. - In https://github.com/prysmaticlabs/prysm/pull/12735/files#diff-a545f9cb2d7ef7f156c12cbef6fd7dc46f45f9e0000681fd79d59c35c38177c9 I used a naming scheme
XXXFromConsensus- can you use the same instead ofConvertXXX? - I don't particularly like the word
Internalin exported function names. From my experience "internal" often means that the function is internal to a module. Maybe we could change this toXXXFromConsensusandXXXToConsensus. In case of exits that would becomeExitsFromConsensusandExitsToConsensus.
f6476a9 to
70143ef
Compare
179b3c0 to
4a9ab6b
Compare
Co-authored-by: Radosław Kapka <[email protected]>
Co-authored-by: Radosław Kapka <[email protected]>
Co-authored-by: Radosław Kapka <[email protected]>
Co-authored-by: Radosław Kapka <[email protected]>
Co-authored-by: Radosław Kapka <[email protected]>
4a9ab6b to
722f540
Compare
What type of PR is this?
Feature
What does this PR do? Why is it needed?
produceBlockV3json Add block v3 endpoint. ethereum/beacon-APIs#339produceBlockV3sszimplements in #12248